#include <stdio.h>
#include <limits.h>

typedef unsigned float_bits;

float_bits float_i2f(int i);
unsigned bits_length(int x);
unsigned bits_mask(unsigned x);
float u2f(unsigned x);

int main()
{
	int i = 123;
	printf("%f\t%f\n", (float)i, u2f(float_i2f(i)));
	i = -123;
	printf("%f\t%f\n", (float)i, u2f(float_i2f(i)));
	i = 0;
	printf("%f\t%f\n", (float)i, u2f(float_i2f(i)));
	i = (~0);
	printf("%f\t%f\n", (float)i, u2f(float_i2f(i)));
	i = (1 << 31);
	printf("%f\t%f\n", (float)i, u2f(float_i2f(i)));

	return 0;
}

float_bits float_i2f(int i)
{
	unsigned sign, exp, frac, bias;
	bias = 127;

	if (i == 0) 
		return 0;
	if (i == INT_MIN) { // -1
		sign = 1;
		exp = 31 + bias; 
		frac = 0; // -1是整数，没有小数部分
		return sign << 31 | exp << 23 | frac;
	}

	sign = i > 0 ? 0 : 1;

	if (i < 0)
		i = -i;

	unsigned bits_num = bits_length(i);
	unsigned fbits_num = bits_num - 1;
	unsigned fbits;

	exp = bias + fbits_num;
	fbits = i & bits_mask(1 << fbits_num - 1);						        
  	if (fbits_num <= 23)
		frac = fbits << (23 - fbits_num);
	else {
		unsigned offset = fbits_num - 23;
		frac = fbits >> offset;
		unsigned round_mid = 1 << (offset - 1);
		unsigned round_part = fbits & bits_mask(1 << offset - 1);
		if (round_part > round_mid)
			++frac;
		else if (round_part == round_mid) {
			if (frac & 0x1)
				++frac;
		}
	}
	return sign << 31 | exp << 23 | frac;
}

unsigned bits_length(int x)
{
	unsigned ux = (unsigned) x;
	unsigned count = 0;
	while (ux > 0) {
		ux >>= 1;
		++count;
	} 
	return count;
}

unsigned bits_mask(unsigned x)
{
	x |= x >> 1;
	x |= x >> 2;
	x |= x >> 4;
	x |= x >> 8;
	x |= x >> 16;

	return x;
}

float u2f(unsigned x)
{
	return *(float *)&x;
}
